package com.uqbar.asteroids.components;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;

import com.uqbar.asteroids.scenes.AsteroidScene;
import com.uqbar.vainilla.DeltaState;
import com.uqbar.vainilla.GameComponent;
import com.uqbar.vainilla.appearances.Circle;
import com.uqbar.vainilla.colissions.CollisionDetector;

public abstract class Asteroid extends GameComponent<AsteroidScene>{
	
	protected int radio;
	protected double i;
	protected double j;
	protected int speed;
	protected double width;
	protected double heigth;
	protected int grupo = 2;
	protected boolean active;
	


	public Asteroid(int radio, int speed, double width, double height){
		this.radio = radio;
		this.speed = speed;
		this.setAppearance(new Circle(Color.RED,radio));
		this.heigth = height;
		this.width = width;		
		this.active = true;
	}
	
	public void onSceneActivated(){
		
		this.definirMovimiento();
		
	    this.i = 1;
		this.j = 1;
		
		double m = Math.sqrt(this.i * this.i + this.j * this.j);
		
		this.i = this.i / m;
		this.j = this.j / m;
		
		super.onSceneActivated();
	}
	
	public void update(DeltaState deltaState){
		if(active){
		double advanced = this.speed * deltaState.getDelta();
			if(colisionaConDisparo(this.getScene().getDisparosEnEscena())){
				this.hasHit();
			}else{
				this.reposicionar();
				this.move(this.i * advanced, this.j * advanced);
			}
			super.update(deltaState);
		}
	}
	
	protected abstract void hasHit();
	
	//define el angulo de salida dependiendo de su posicion.
	protected void definirMovimiento(){
		Random random = new Random();
		if(this.getY()<0){
			if(random.nextDouble() > 0.5){	
				this.i = random.nextGaussian();
				this.j = 1;
			}else{
				this.i = (random.nextGaussian() *-1);
				this.j = 1;
			}
		}
		
		if(this.getX()<0){
			if(random.nextDouble() > 0.5){	
				this.i = 1;
				this.j = random.nextGaussian();
			}else{
				this.i = 1;
				this.j =  (random.nextGaussian() *-1);
			}
		}
		
		if(this.getX()> this.getGame().getDisplayWidth()){
			if(random.nextDouble() > 0.5){	
				this.i = -1;
				this.j = random.nextGaussian();
			}else{
				this.i = -1;
				this.j = (random.nextGaussian() *-1);
			}
		}
		
		if(this.getY()> this.getGame().getDisplayHeight()){
			if(random.nextDouble() > 0.5){	
				this.i = random.nextGaussian();
				this.j = -1;
			}else{
				this.i = (random.nextGaussian() *-1);
				this.j = -1;
			}
		}
		

			
	}
	
	// decide donde van a aparecer los meteoros.
	public void definirPosicion(double width, double height){
		Random random = new Random();
		int limite = 200;
		// decide lado derecho/ izquierdo  o superior/inferior de la pantalla
		if(random.nextDouble() > 0.5){
			//elige al azar una posicion en Y con un margen minimo y maximo.
			this.setY(Math.random()*(limite - (height-limite))+(height-limite));
			//decide derecha o izquierda de la pantalla
			if(random.nextDouble() > 0.5){
				this.setX(width + this.radio * 2);
			}else{
				this.setX(0 - this.radio * 2);
			}
		}else{
			//elige al azar una posicion en X con un margen minimo y maximo.
			this.setX(Math.random()*(limite - (width-limite))+(width-limite));
			//Decide lado superior, o inferior de la pantalla.
			if(random.nextDouble()> 0.5){
				this.setY(height + this.radio * 2);
			}else{
				this.setY(0 - this.radio * 2);
			}
		}
	}
	

	protected void reposicionar(){
		
		if(this.getY()>this.heigth + this.radio){
			this.setY( 0 - this.radio * 2);
		}
		
		if((this.getY()+this.radio*2)< (0)){
			this.setY( this.heigth);
		}		
		
		if(this.getX()> this.width +this.radio){
			this.setX( 0 - this.radio*2 );
		}
		
		if((this.getX() + this.radio * 2) < 0 ){
			this.setX( this.width );
		}
		
	}
	
	protected boolean colisionaConDisparo(ArrayList<CircleShoot> disparos){
		boolean colsiono = false;
		int i;
		for(i=0;i<disparos.size();i++){
			CircleShoot disparo = disparos.get(i);
			if(disparo.getGrupo() != this.grupo){
				colsiono = CollisionDetector.INSTANCE.collidesCircleAgainstRect(
				this.getX(), this.getY(), 
				this.getAppearance().getWidth() / 2, disparo.getX(),
				disparo.getY(), disparo.getAppearance().getWidth(),
				disparo.getAppearance().getHeight());
					
					if(colsiono){
						disparo.toOutScreen();
						this.getScene().shootToPool(disparo);
					}
			}
		}
		
		return colsiono;
		
	}
	
	protected void definirAnguloDeSalidaDespuesDeImpacto(){
		Random random = new Random();
		this.i = random.nextGaussian();
		this.j = random.nextGaussian();
	}
	
	public void toOutScreen() {
		this.setX(-100);
		this.active = false;
	}
	
	public void activar(){
		this.active = true;
	}
	
}
